package com.ironman.h6b1gw.listener;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import com.ironman.h6b1gw.threadpool.ThreadPool;
import com.ironman.h6b1gw.tlv.TLVDecoder;
import lombok.extern.slf4j.Slf4j;
import org.dromara.mica.mqtt.codec.MqttQoS;
import org.dromara.mica.mqtt.spring.client.MqttClientSubscribe;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GwDataListener {

    /**
     * topic: /v1/gw/gw10001332/1000005860/up_raw
     * 0464  BIT15=>合闸状态  BIT14=>分闸状态
     */
    @MqttClientSubscribe(value = "$share/iot//v1/gw/+/+/up_raw", qos = MqttQoS.QOS1)
    public void deviceUpRaw(String topic, byte[] payload) {
        String devId = topic.split("/")[4];
        handle("device", devId, topic, payload);
    }

    private void handle(String dataSource, String sn, String topic, byte[] payload) {
        ThreadPool.FIXED_EXECUTOR.execute(() -> {
            String message = new String(payload, StandardCharsets.UTF_8);
            // log.info("\n↑ {} \n{}", topic, message);
            List<TLVDecoder.TlvEntry> tlvEntries = TLVDecoder.decode(HexUtil.decodeHex(message));
            tlvEntries = tlvEntries.stream().sorted(Comparator.comparing(TLVDecoder.TlvEntry::getType)).collect(Collectors.toList());
            Map<String, String> tlvEntryMap = tlvEntries.stream().collect(Collectors.toMap(TLVDecoder.TlvEntry::getType, TLVDecoder.TlvEntry::getValue));
            tlvEntryMap.put(topic, message);
            //log.info("数据来源: {}\n{}", dataSource, JSONUtil.toJsonPrettyStr(tlvEntryMap));
            /*
              BIT15:合闸状态
              BIT14:分闸状态
              BIT13:锁定状态
              BIT12:漏电自检中
              BIT11:费控欠费
              BIT10:时钟电池欠压
              BIT9:当前运行时段1(尖时段)
              BIT8:当前运行时段2(峰时段)
              BIT7:当前运行时段3(平时段)
              BIT6:当前运行时段4(谷时段)
              BIT5:漏电故障
              BIT4:485通讯故障
              BIT3:漏电报警
              BIT2:内部温度预警
              BIT1:开关寿命预警
              BIT0:开关寿命报警
             */
            // 0100010000000000
            // 1000010000000000
            String value = tlvEntryMap.get("0464");
            if (StrUtil.isBlank(value)) {
                return;
            }
            String bit = String.format("%16s", Integer.toBinaryString(Integer.parseInt(value, 16)))
                    .replace(' ', '0');
            log.info("设备ID(devid): {}, 地址: {}, 闸状态: {}", sn, "0464", bit);
        });
    }
}